package restdom.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
import org.springframework.web.util.WebUtils;

/**
 * Risolve il nome del metodo da invocare sul MultiActionController
 * in base a:
 *  <ol>
 *    <li>Il metodo HTTP utilizzato (HEAD, GET, POST, PUT, DELETE) oppure</li>
 *    <li>Un parametro postTunnelingParameter indicato in una richiesta POST</li>
 *  </ol>
 */
public class RestMethodNameResolver implements MethodNameResolver {

	public static final String DEFAULT_POST_TUNNELING_PARAMETER = "_method";

	/**
	 * Parametro POST che contiene il nome del metodo HTTP realmente
	 * inteso. Utile per i browser, che tipicamente non consentono
	 * l'uso di metodi PUT, HEAD, DELETE in modo diretto.
	 */
	private String postTunnelingParameter = DEFAULT_POST_TUNNELING_PARAMETER;
	
	public String getPostTunnelingParameter() {
		return postTunnelingParameter;
	}

	public void setPostTunnelingParameter(String postTunnelingParameter) {
		this.postTunnelingParameter = postTunnelingParameter;
	}
	
	private Map<String,String> methodMap;
	
	public RestMethodNameResolver() {
		methodMap = new HashMap<String,String>();
		methodMap.put(RestController.METHOD_HEAD,   "head");
		methodMap.put(RestController.METHOD_GET,    "read");
		methodMap.put(RestController.METHOD_POST,   "create");
		methodMap.put(RestController.METHOD_PUT,    "update");
		methodMap.put(RestController.METHOD_DELETE, "delete");
	}
	
	//~ MethodNameResolver implementation ==============================
	public String getHandlerMethodName(HttpServletRequest request)
			throws NoSuchRequestHandlingMethodException {
		
		// metodo HTTP
		String methodName = request.getMethod();
		
		// sto facendo un 'POST tunneling'?
		if (RestController.METHOD_POST.equals(methodName) &&
				WebUtils.hasSubmitParameter(request, getPostTunnelingParameter())) {
			methodName = request.getParameter(getPostTunnelingParameter());
		}
		
		if (methodMap.containsKey(methodName)) {
			return methodMap.get(methodName);
		}
		throw new NoSuchRequestHandlingMethodException(request);
	}
}
